package com.vca.service.service.Impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vca.common.constants.CategoryConstants;
import com.vca.common.exception.VcaException;
import com.vca.common.model.category.Category;
import com.vca.common.model.course.Course;
import com.vca.common.model.course.CourseAbout;
import com.vca.common.model.course.CoursePackage;
import com.vca.common.model.exhibition.Exhibition;
import com.vca.common.model.talk.Talk;
import com.vca.common.model.vca_product.VcaProduct;
import com.vca.common.request.CourseAboutAddRequest;
import com.vca.common.response.CourseAboutAdminResponse;
import com.vca.common.utils.VcaUtil;
import com.vca.service.dao.course.CourseAboutDao;
import com.vca.service.service.*;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * <p>
 * 相关课程表（课程） 服务实现类
 * </p>
 *
 * @author chenBing
 * @since 2022-10-17
 */
@Service
@Slf4j
public class CourseAboutServiceImpl extends ServiceImpl<CourseAboutDao, CourseAbout> implements CourseAboutService {

    @Autowired
    private CourseAboutDao dao;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private CourseService courseService;

    @Autowired
    private CoursePackageService coursePackageService;

    @Autowired
    private TalkService talkService;

    @Autowired
    private ExhibitionService exhibitionService;

    @Autowired
    private VcaProductService vcaProductService;

    @Autowired
    private CategoryService categoryService;


    /**
     * 添加大量相关课程
     *
     * @param courseAboutList
     * @return
     * @author Li
     * @date 2022/11/18 10:41
     */
    @Override
    public boolean addCourseAboutList(List<CourseAbout> courseAboutList) {
        courseAboutList.forEach(e->{
            switch (e.getTypeCourse()){
                case 1:
                    e.setTypeCourse(2);
                    break;
                case 2:
                    e.setTypeCourse(3);
                    break;
                case 3:
                    e.setTypeCourse(4);
                    break;
                case 4:
                    e.setTypeCourse(1);
                    break;
                default:
                    break;
            }
        });
        return transactionTemplate.execute(e -> {
            courseAboutList.forEach(g -> {
                dao.insert(g);
            });
            return Boolean.TRUE;
        });
    }

    /**
     * 校验添加的相关课程是否存在
     *
     * @param listMap
     * @author Li
     * @date 2022/11/22 14:35
     */
    @Override
    public void checkWhetherCourseAbout(Map<Integer, List<CourseAboutAddRequest>> listMap) {
        if (ObjectUtil.isEmpty(listMap)){
            return;
        }
        AtomicReference<VcaException> vcaException = new AtomicReference();
        //验证判断添加的相关课程和商品是否存在
        listMap.forEach((k, v) -> {
            //取出分组后的相关课程和商品的id
            List<Long> aboutId = v.stream().map(CourseAboutAddRequest::getAboutId).collect(Collectors.toList());
            switch (k) {
                case 0:
                    List<Course> courseList = courseService.list(new LambdaQueryWrapper<Course>()
                            .in(Course::getId, aboutId).eq(Course::getIsRecycle, 0)
                            .eq(Course::getIsDeleted, 0));
                    if (ObjectUtil.isEmpty(courseList)) {
                        vcaException.set(new VcaException("选中的课程不存在"));
                    }
                    break;
                case 1:
                    List<Talk> talks = talkService.list(new LambdaQueryWrapper<Talk>()
                            .in(Talk::getId, aboutId).eq(Talk::getIsRecycle, 0)
                            .eq(Talk::getIsDeleted, 0));
                    if (ObjectUtil.isEmpty(talks)) {
                        vcaException.set(new VcaException("选中的讲座不存在"));
                    }
                    break;
                case 2:

                    List<Exhibition> ee = exhibitionService.list(new LambdaQueryWrapper<Exhibition>()
                            .in(Exhibition::getId, aboutId).eq(Exhibition::getIsRecycle, 0)
                            .eq(Exhibition::getIsDeleted, 0));
                    if (ObjectUtil.isEmpty(ee)) {
                        vcaException.set(new VcaException("选中的展览不存在"));
                    }
                    break;
                case 3:

                    List<VcaProduct> products = vcaProductService.list(new LambdaQueryWrapper<VcaProduct>()
                            .in(VcaProduct::getId, aboutId).eq(VcaProduct::getIsRecycle, 0)
                            .eq(VcaProduct::getIsDeleted, 0));
                    if (ObjectUtil.isEmpty(products)) {
                        vcaException.set(new VcaException("选中的商品不存在"));
                    }
                    break;
                case 4:

                    List<CoursePackage> coursePackageList = coursePackageService.list(new LambdaQueryWrapper<CoursePackage>()
                            .in(CoursePackage::getId, aboutId).eq(CoursePackage::getIsRecycle, 0)
                            .eq(CoursePackage::getIsDeleted, 0));
                    if (ObjectUtil.isEmpty(coursePackageList)) {
                        vcaException.set(new VcaException("选中的套课不存在"));
                    }
                    break;
                default:
                    vcaException.set(new VcaException("参数错误"));
                    break;
            }
        });
        //判断是否有不存在的相关课程或商品
        if (ObjectUtil.isNotEmpty(vcaException.get())) {
            throw vcaException.get();
        }
    }

    /**
     * 校验添加的相关课程是否存在
     *
     * @param listMap
     * @author Li
     * @date 2022/11/22 14:35
     */
    @Override
    public List<CourseAboutAdminResponse> getAdminCourseAbout(Map<Integer, List<CourseAbout>> listMap, Map<String, List<HashMap<String, Object>>> courseAdminConfig) {
        List<Category> categoryList = categoryService.list(new LambdaQueryWrapper<Category>().in(Category::getType, CategoryConstants.CATEGORY_TYPE_PRODUCT, CategoryConstants.CATEGORY_TYPE_COURSE));
        Map<Integer, List<Category>> categories = categoryList.stream().collect(Collectors.groupingBy(Category::getId));
        List<Category> list = categoryService.list(new LambdaQueryWrapper<Category>().eq(Category::getType, CategoryConstants.CATEGORY_TYPE_COURSE));
        Map<Integer, List<Category>> courseTypes = list.stream().collect(Collectors.groupingBy(Category::getId));
        List<CourseAboutAdminResponse> aboutList = new ArrayList();
        List<HashMap<String, Object>> price = courseAdminConfig.get("priceList");
        List<HashMap<String, Object>> address = courseAdminConfig.get("addressList");
        listMap.forEach((k, v) -> {
            //取出分组后的相关课程和商品的id
            List<Long> aboutId = v.stream().map(CourseAbout::getAboutId).collect(Collectors.toList());
            Map<Long, List<CourseAbout>> type = v.stream().collect(Collectors.groupingBy(e -> e.getAboutId()));
            switch (k) {
                case 0:
                    aboutId.forEach(e -> {
                        Course course = courseService.getOne(new LambdaQueryWrapper<Course>()
                                .eq(Course::getId, e));
                        if (ObjectUtil.isNotEmpty(course)) {
                            CourseAboutAdminResponse courseAboutAdminResponse = new CourseAboutAdminResponse();
                            BeanUtils.copyProperties(course, courseAboutAdminResponse);
                            courseAboutAdminResponse.setSort(type.get(course.getId()).get(0).getSort());
                            courseAboutAdminResponse.setId(course.getId());
                            courseAboutAdminResponse.setCoverImage(course.getCover());
                            courseAboutAdminResponse.setAboutId(course.getId());
                            courseAboutAdminResponse.setTypeCourse(0);
                            courseAboutAdminResponse.setType(type.get(course.getId()).get(0).getType());
                            courseAboutAdminResponse.setCourseAboutId(type.get(course.getId()).get(0).getId());
                            courseAboutAdminResponse.setCourseType(courseTypes.get(course.getCourseTypeId().intValue()).get(0).getName());
                            price.forEach(g -> {
                                Map map = JSON.parseObject(JSONObject.toJSONString(g), Map.class);
                                if (map.get("id").equals(course.getCoursePriceId())) {
                                    courseAboutAdminResponse.setPrice(map.get("coursePrice").toString());
                                }
                            });
                            aboutList.add(courseAboutAdminResponse);
                        }
                    });
                    break;
                case 2:
                    aboutId.forEach(e -> {
                        Talk talk = talkService.getOne(new LambdaQueryWrapper<Talk>()
                                .in(Talk::getId, e));
                        if (ObjectUtil.isNotEmpty(talk)) {
                            CourseAboutAdminResponse courseAboutAdminResponse = new CourseAboutAdminResponse();
                            BeanUtils.copyProperties(talk, courseAboutAdminResponse);
                            courseAboutAdminResponse.setSort(type.get(talk.getId()).get(0).getSort());
                            courseAboutAdminResponse.setId(talk.getId());
                            courseAboutAdminResponse.setAboutId(talk.getId());
                            courseAboutAdminResponse.setTypeCourse(1);
                            courseAboutAdminResponse.setType(type.get(talk.getId()).get(0).getType());
                            courseAboutAdminResponse.setCourseAboutId(type.get(talk.getId()).get(0).getId());
                            courseAboutAdminResponse.setCoverImage(talk.getCoverImage());
                            courseAboutAdminResponse.setCourseType(talk.getTalkType() == 1 ? "线上讲座" : "线下讲座");
                            courseAboutAdminResponse.setPrice(talk.getPrice().toString());
                            aboutList.add(courseAboutAdminResponse);
                        }
                    });
                    break;
                case 3:
                    aboutId.forEach(e -> {
                        Exhibition exhibition = exhibitionService.getOne(new LambdaQueryWrapper<Exhibition>()
                                .in(Exhibition::getId, e));
                        if (ObjectUtil.isNotEmpty(exhibition)) {
                            CourseAboutAdminResponse courseAboutAdminResponse = new CourseAboutAdminResponse();
                            BeanUtils.copyProperties(exhibition, courseAboutAdminResponse);
                            courseAboutAdminResponse.setSort(type.get(exhibition.getId()).get(0).getSort());
                            courseAboutAdminResponse.setId(exhibition.getId());
                            courseAboutAdminResponse.setCoverImage(exhibition.getCover());
                            courseAboutAdminResponse.setAboutId(exhibition.getId());
                            courseAboutAdminResponse.setCourseAboutId(type.get(exhibition.getId()).get(0).getId());
                            courseAboutAdminResponse.setTypeCourse(2);
                            courseAboutAdminResponse.setType(type.get(exhibition.getId()).get(0).getType());
                            address.forEach(g -> {
                                Map map = JSON.parseObject(JSONObject.toJSONString(g), Map.class);
                                if (map.get("id").equals(exhibition.getCourseAddressId())) {
                                    courseAboutAdminResponse.setCourseAddress(map.get("courseAddress").toString() + map.get("courseAddressInfo").toString());
                                }
                            });
                            aboutList.add(courseAboutAdminResponse);
                        }
                    });
                    break;
                case 4:
                    aboutId.forEach(e -> {
                        VcaProduct products = vcaProductService.getOne(new LambdaQueryWrapper<VcaProduct>()
                                .in(VcaProduct::getId, e));
                        if (ObjectUtil.isNotEmpty(products)) {
                            CourseAboutAdminResponse courseAboutAdminResponse = new CourseAboutAdminResponse();
                            BeanUtils.copyProperties(products, courseAboutAdminResponse);
                            courseAboutAdminResponse.setSort(type.get(products.getId().longValue()).get(0).getSort());
                            courseAboutAdminResponse.setId(products.getId().longValue());
                            courseAboutAdminResponse.setAboutId(products.getId().longValue());
                            courseAboutAdminResponse.setTypeCourse(3);
                            courseAboutAdminResponse.setCourseAboutId(type.get(products.getId().longValue()).get(0).getId());
                            courseAboutAdminResponse.setType(type.get(products.getId().longValue()).get(0).getType());
                            courseAboutAdminResponse.setCoverImage(products.getCoverImage());
                            courseAboutAdminResponse.setCourseType(categories.get(products.getCid()).get(0).getName());
                            courseAboutAdminResponse.setPrice(products.getPrice().toString());
                            aboutList.add(courseAboutAdminResponse);
                        }
                    });
                    break;
                case 1:
                    aboutId.forEach(e -> {
                        CoursePackage coursePackage = coursePackageService.getOne(new LambdaQueryWrapper<CoursePackage>()
                                .in(CoursePackage::getId, e));
                        if (ObjectUtil.isNotEmpty(coursePackage)) {
                            CourseAboutAdminResponse courseAboutAdminResponse = new CourseAboutAdminResponse();
                            BeanUtils.copyProperties(e, courseAboutAdminResponse);
                            courseAboutAdminResponse.setSort(type.get(coursePackage.getId()).get(0).getSort());
                            courseAboutAdminResponse.setName(coursePackage.getName());
                            courseAboutAdminResponse.setId(coursePackage.getId());
                            courseAboutAdminResponse.setCourseAboutId(type.get(coursePackage.getId()).get(0).getId());
                            courseAboutAdminResponse.setAboutId(coursePackage.getId());
                            courseAboutAdminResponse.setTypeCourse(4);
                            courseAboutAdminResponse.setType(type.get(coursePackage.getId()).get(0).getType());
                            courseAboutAdminResponse.setCoverImage(coursePackage.getCoverImage());
                            courseAboutAdminResponse.setCourseType(courseTypes.get(coursePackage.getCourseTypeId().intValue()).get(0).getName());
                            price.forEach(g -> {
                                Map map = JSON.parseObject(JSONObject.toJSONString(g), Map.class);
                                if (map.get("id").equals(coursePackage.getCoursePackagePriceId())) {
                                    courseAboutAdminResponse.setPrice(map.get("coursePrice").toString());
                                }
                            });
                            aboutList.add(courseAboutAdminResponse);
                        }
                    });
                    break;
                default:
                    break;
            }
        });
        return aboutList;
    }

    /**
     * 相关课程修改
     *
     * @param courseAboutList
     * @return
     * @author Li
     * @date 2022/11/22 15:15
     */
    @Override
    public boolean updateCourseAboutList(List<CourseAbout> courseAboutList, Long mainAboutId) {
        //查询当前的相关课程
        LambdaQueryWrapper<CourseAbout> wrapper = new LambdaQueryWrapper();
        wrapper.eq(CourseAbout::getAboutMainId, mainAboutId);
        List<CourseAbout> courseAbouts = dao.selectList(wrapper);
        List<Long> ids = new ArrayList();
        courseAboutList.forEach(e->{
            switch (e.getTypeCourse()){
                case 1:
                    e.setTypeCourse(2);
                    break;
                case 2:
                    e.setTypeCourse(3);
                    break;
                case 3:
                    e.setTypeCourse(4);
                    break;
                case 4:
                    e.setTypeCourse(1);
                    break;
                default:
                    break;
            }
        });

        //从数据获取到的相关列表
        Map<String, CourseAbout> listMap = new HashMap<>();
        courseAbouts.forEach(e -> {
            Long id = e.getId();
            //判断 id是否为 空 为空赋值为0
            if (ObjectUtil.isEmpty(e.getId())) {
                id = 0L;
            }
            //组合 key 相关课程表主键id , 课程主键id , 相关课程类型 0 = 课程 1=讲座 2=展览 3=商品 4=套课
            //组成 key
            String key = +id + "," + e.getAboutId() + "," + e.getTypeCourse();
            listMap.put(key, e);
        });
        //从前端传回的 相关课程列表
        Map<String, CourseAbout> map = new HashMap<>();
        courseAboutList.forEach(e -> {
            Long id = e.getId();
            //判断 id是否为 空 为空赋值为0
            if (ObjectUtil.isEmpty(e.getId())) {
                id = 0L;
            }
            //组合 key 相关课程表主键id , 课程主键id , 相关课程类型 0 = 课程 1=讲座 2=展览 3=商品 4=套课
            //组成 key
            String key = +id + "," + e.getAboutId() + "," + e.getTypeCourse();
            map.put(key, e);
        });
        List<String> keys = new ArrayList<>();
        listMap.forEach((k, v) -> {
            List<Integer> integers = VcaUtil.stringToArray(k);
            Integer i1 = integers.get(0);
            Integer i2 = integers.get(1);
            Integer i3 = integers.get(2);
            map.forEach((key, value) -> {
                List<Integer> integerList = VcaUtil.stringToArray(key);
                Integer l1 = integerList.get(0);
                Integer l2 = integerList.get(1);
                Integer l3 = integerList.get(2);
                //进行比较 从数据库获取到的 前端是否也有
                if (i1.equals(l1) && i2.equals(l2) && i3.equals(l3)) {
                    //两者都有添加到删除列表
                    keys.add(k);
                }
            });
        });
        keys.forEach(e -> {
            //将从数据库获取 和 前端相同的删除
            listMap.remove(e);
        });
        //获得前端未传的 id
        listMap.forEach((k, v) -> {
            ids.add(v.getId());
        });

        return transactionTemplate.execute(e -> {
            courseAboutList.forEach(g -> {
                //判断是否传 id 未传 说明为新增 进行添加操作
                if (ObjectUtil.isEmpty(g.getId())) {
                    dao.insert(g);
                } else {
                    //如果传 可能进行过修改 执行修改操作
                    dao.updateById(g);
                }
            });
            //如果数据库存在前端未传的相关课程 进行删除
            if (ObjectUtil.isNotEmpty(ids)) {
                dao.deleteBatchIds(ids);
            }
            return Boolean.TRUE;
        });
    }

    /**
     * @param ids
     * @return boolean
     * @description 根据id列表逻辑删除
     * @methodName delByids
     * * @param ids
     * @author Li
     * @date 2023/1/3 16:35
     */
    @Override
    public boolean delByids(List<Long> ids) {
        if (ObjectUtil.isEmpty(ids)){
            return true;
        }
        return transactionTemplate.execute(e->{
            dao.deleteBatchIds(ids);
            return Boolean.TRUE;
        });
    }
}
